/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package conceitosgame.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author jeferson
 */
public class FormatoBmp {
    public byte[] imagemArquivo;
    public File caminho;
    public String descricao;

    //cabeçalho de 14 bytes
    public byte[] BfType;          // assinatura do arquivo
    public byte[] BfSize;          // tamanho do arquivo
    public byte[] BfReser1;        // campo reservado
    public byte[] BfReser2;        // campo reservado
    public byte[] BfOffSetBits;    // deslocamento
    //cabeçalho de 40 bytes
    public byte[] BiSize;          // tamanho do cabecalho
    public byte[] BiWidth;         //largura da imagem
    public byte[] BiHeight;        // altura da imagem
    public byte[] BiPlanes;        // numero de planos
    public byte[] BiBitCount;      // quantidade bits por pixel
    public byte[] BiCompress;      // compressao
    public byte[] BiSizeImag;      // tamanho da imagem
    public byte[] BiXPPMeter;      // resolucao horizontal
    public byte[] BiYPPMeter;      // resolucao vertical
    public byte[] BiClrUsed;       // numero de cores usada na imagem
    public byte[] BiClrImpor;      // numero de cores importantes
    //palheta de cores yuv e normal
    public Cores[] paleta;         //paleta de cores pode ir até 256 com 4 bytes cada posição
    //bytes da imagem
    public byte[] imagem;

    public FormatoBmp() {
        BfType = new byte[2];       // 0-1
        BfSize = new byte[4];       // 2 - 5
        BfReser1 = new byte[2];     // 6 - 7
        BfReser2 = new byte[2];     // 8 - 9
        BfOffSetBits = new byte[4]; // 10 - 13
        BiSize = new byte[4];       // 14 - 17
        BiWidth = new byte[4];      // 18 - 21
        BiHeight = new byte[4];     // 22 - 25
        BiPlanes = new byte[2];     // 26 - 27
        BiBitCount = new byte[2];   // 28 - 29
        BiCompress = new byte[4];   // 30 - 33
        BiSizeImag = new byte[4];   // 34 - 37
        BiXPPMeter = new byte[4];   // 38 - 41
        BiYPPMeter = new byte[4];   // 42 - 45
        BiClrUsed = new byte[4];    // 46 - 49
        BiClrImpor = new byte[4];   // 50 - 53
        descricao = "";
    }

    public int getBiHeight() {
        return Conversoes.byteArray2Int4(BiHeight);
    }

    public int getBiWidth() {
        return Conversoes.byteArray2Int4(BiWidth);
    }

    public int getBiBitCount() {
        return Conversoes.byteArray2Int2(BiBitCount);
    }

    public int getBfSize() {
        return Conversoes.byteArray2Int4(BfSize);
    }

    public void setBfOffSetBits(byte novo) {
    }
    
    public byte[] gerarVetorBmp(FormatoBmp bmp) {
        byte[] vetor = new byte[Conversoes.byteArray2Int4(bmp.BfSize)];

            for (int i = 0; i < 54; i++) {
                if (i == 0 || i == 1) {
                    vetor[i] = bmp.BfType[i];
                }
                if (i >= 2 && i <= 5) {
                    vetor[i] = bmp.BfSize[i - 2];
                }
                if (i == 6 || i == 7) {
                    vetor[i] = bmp.BfReser1[i - 6];
                }
                if (i == 8 || i == 9) {
                    vetor[i] = bmp.BfReser2[i - 8];
                }
                if (i >= 10 && i <= 13) {
                    vetor[i] = bmp.BfOffSetBits[i - 10];
                }
                if (i >= 14 && i <= 17) {
                    vetor[i] = bmp.BiSize[i - 14];
                }
                if (i >= 18 && i <= 21) {
                    vetor[i] = bmp.BiWidth[i - 18];
                }
                if (i >= 22 && i <= 25) {
                    vetor[i] = bmp.BiHeight[i - 22];
                }
                if (i == 26 || i == 27) {
                    vetor[i] = bmp.BiPlanes[i - 26];
                }
                if (i == 28 || i == 29) {
                    vetor[i] = bmp.BiBitCount[i - 28];
                }
                if (i >= 30 && i <= 33) {
                    vetor[i] = bmp.BiCompress[i - 30];
                }
                if (i >= 34 && i <= 37) {
                    vetor[i] = bmp.BiSizeImag[i - 34];
                }
                if (i >= 38 && i <= 41) {
                    vetor[i] = bmp.BiXPPMeter[i - 38];
                }
                if (i >= 42 && i <= 45) {
                    vetor[i] = bmp.BiYPPMeter[i - 42];
                }
                if (i >= 46 && i <= 49) {
                    vetor[i] = bmp.BiClrUsed[i - 46];
                }
                if (i >= 50 && i <= 53) {
                    vetor[i] = bmp.BiClrImpor[i - 50];
                }
            }

            short tamanho = Conversoes.byteArray2Short(bmp.BiBitCount);
            if (tamanho <= 8) {
                for (int i = 54; i < bmp.paleta.length; i++) {
                    vetor[i] = (byte) bmp.paleta[i - 54].getR();
                    vetor[i] = (byte) bmp.paleta[i - 54].getG();
                    vetor[i] = (byte) bmp.paleta[i - 54].getB();
                    vetor[i] = (byte) bmp.paleta[i - 54].getA();
                }
                int deslocamento = 54 + bmp.paleta.length;
                for (int i = deslocamento; i < bmp.imagem.length; i++) {
                    vetor[i] = bmp.imagem[i - deslocamento];
                }
            } else {
                for (int i = 54; i < bmp.imagem.length; i++) {
                    vetor[i] = bmp.imagem[i - 54];
                }
            }
        return vetor;
    }
    
    public FormatoBmp construirBmp(File arquivo){
        FormatoBmp novoFormato = new FormatoBmp();
        
        //definindo tamanho do tamanho do arquivo de entrada e convertendo o mesmo para um buffer de bytes
        this.imagemArquivo = new byte[(int)arquivo.length()];
        InputStream pegarBytes = null;
        try {
            pegarBytes = new FileInputStream(arquivo);
            caminho = arquivo;
        } catch (FileNotFoundException ex) {
            Logger.getLogger(FormatoBmp.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            //pega o arquivo que esta na inputStream e convete para um buffer de bytes passado por parametro
            pegarBytes.read(imagemArquivo);
        } catch (IOException ex) {
            Logger.getLogger(FormatoBmp.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        //gerando a estrutura do bmp
        for (int i = 0; i < 54; i++) {            
            if (i == 0 || i == 1) 
                novoFormato.BfType[i] = imagemArquivo[i];
            if (i >= 2 && i <= 5) 
                novoFormato.BfSize[i - 2] = imagemArquivo[i];
            if (i == 6 || i == 7) 
                novoFormato.BfReser1[i - 6] = imagemArquivo[i];
            if (i == 8 || i == 9) 
                novoFormato.BfReser2[i - 8] = imagemArquivo[i];
            if (i >= 10 && i <= 13) 
                novoFormato.BfOffSetBits[i - 10] = imagemArquivo[i];
            if (i >= 14 && i <= 17) 
                novoFormato.BiSize[i - 14] = imagemArquivo[i];
            if (i >= 18 && i <= 21) 
                novoFormato.BiWidth[i - 18] = imagemArquivo[i];
            if (i >= 22 && i <= 25) 
                novoFormato.BiHeight[i - 22] = imagemArquivo[i];
            if (i == 26 || i == 27)
                novoFormato.BiPlanes[i - 26] = imagemArquivo[i];
            if (i == 28 || i == 29) 
                novoFormato.BiBitCount[i - 28] = imagemArquivo[i];
            if (i >= 30 && i <= 33) 
                novoFormato.BiCompress[i - 30] = imagemArquivo[i];
            if (i >= 34 && i <= 37)
                novoFormato.BiSizeImag[i - 34] = imagemArquivo[i];
            if (i >= 38 && i <= 41) 
                novoFormato.BiXPPMeter[i - 38] = imagemArquivo[i];
            if (i >= 42 && i <= 45)
                novoFormato.BiYPPMeter[i - 42] = imagemArquivo[i];
            if (i >= 46 && i <= 49) 
                novoFormato.BiClrUsed[i - 46] = imagemArquivo[i];
            if (i >= 50 && i <= 53) 
                novoFormato.BiClrImpor[i - 50] = imagemArquivo[i];
        }
        
        short tamanho = Conversoes.byteArray2Short(novoFormato.BiBitCount);        
        //imagem de 255 cores, caso seja maior que 8 a imagem é trueCoolor: ignora a paleta de cores
        if(tamanho <= 8){            
            //criando a palheta de cores
            int numeroCores = (int) Math.pow(2, tamanho);
            novoFormato.paleta = new Cores[numeroCores];
            int cont = 0;
            
            //o for vai da posição 54 até o numero de cores vezes quatro pois cada cor tem 4 bytes
            //indo até o numero de cores mais 54 bytes para descontar as 54 posições já lidas
            for(int i = 54; i < ((numeroCores*4)+54); i+=4){       
                Cores novo = new Cores();
                novo.setR(imagemArquivo[i] & 0xFF);
                novo.setG(imagemArquivo[i+1] & 0xFF);
                novo.setB(imagemArquivo[i+2] & 0xFF);
                novo.setA(imagemArquivo[i+3] & 0xFF);
                novoFormato.paleta[cont] = novo;
                cont++;
            }
        }
        
        //gerando vetor de dados da imagem isso independe ta paleta de cores
        int inicioAreaDados = Conversoes.byteArray2Int4(novoFormato.BfOffSetBits);  //pega o inicio da area da imagem
        int tamanhoArquivo = Conversoes.byteArray2Int4(novoFormato.BfSize);         //pega o tamanho do arquivo em bytes
        int tamanhoImagem = tamanhoArquivo - inicioAreaDados;
        novoFormato.imagem = new byte[tamanhoImagem];

        for(int i = inicioAreaDados; i < tamanhoArquivo; i++){
            novoFormato.imagem[i - inicioAreaDados] = imagemArquivo[i];
        }
        
        return novoFormato;
    
    }

    @Override
    public String toString() {
        return descricao;
    }
    
    public void copiarBmp(FormatoBmp original) {

        for (int i = 0; i < 54; i++) {
            if (i == 0 || i == 1) {
                this.BfType[i] = original.BfType[i];
            }
            if (i >= 2 && i <= 5) {
                this.BfSize[i - 2] = original.BfSize[i - 2];
            }
            if (i == 6 || i == 7) {
                this.BfReser1[i - 6] = original.BfReser1[i - 6];
            }
            if (i == 8 || i == 9) {
                this.BfReser2[i - 8] = original.BfReser2[i - 8];
            }
            if (i >= 10 && i <= 13) {
                this.BfOffSetBits[i - 10] = original.BfOffSetBits[i - 10];
            }
            if (i >= 14 && i <= 17) {
                this.BiSize[i - 14] = original.BiSize[i - 14];
            }
            if (i >= 18 && i <= 21) {
                this.BiWidth[i - 18] = original.BiWidth[i - 18];
            }
            if (i >= 22 && i <= 25) {
                this.BiHeight[i - 22] = original.BiHeight[i - 22];
            }
            if (i == 26 || i == 27) {
                this.BiPlanes[i - 26] = original.BiPlanes[i - 26];
            }
            if (i == 28 || i == 29) {
                this.BiBitCount[i - 28] = original.BiBitCount[i - 28];
            }
            if (i >= 30 && i <= 33) {
                this.BiCompress[i - 30] = original.BiCompress[i - 30];
            }
            if (i >= 34 && i <= 37) {
                this.BiSizeImag[i - 34] = original.BiSizeImag[i - 34];
            }
            if (i >= 38 && i <= 41) {
                this.BiXPPMeter[i - 38] = original.BiXPPMeter[i - 38];
            }
            if (i >= 42 && i <= 45) {
                this.BiYPPMeter[i - 42] = original.BiYPPMeter[i - 42];
            }
            if (i >= 46 && i <= 49) {
                this.BiClrUsed[i - 46] = original.BiClrUsed[i - 46];
            }
            if (i >= 50 && i <= 53) {
                this.BiClrImpor[i - 50] = original.BiClrImpor[i - 50];
            }
        }

        this.imagem = new byte[original.imagem.length];
        
        for (int i = 0; i < original.imagem.length; i++) {
            this.imagem[i] = original.imagem[i];
        }
    }
    
    public byte[] gerarVetorBytes(){
        byte[] vetor = new byte[Conversoes.byteArray2Int4(this.BfSize)];
        
        for (int i = 0; i < 54; i++) {            
            if (i == 0 || i == 1) 
                vetor[i] = this.BfType[i];
            if (i >= 2 && i <= 5)
                vetor[i] = this.BfSize[i - 2];
            if (i == 6 || i == 7) 
                vetor[i] = this.BfReser1[i - 6];
            if (i == 8 || i == 9) 
                vetor[i] = this.BfReser2[i - 8];
            if (i >= 10 && i <= 13) 
                vetor[i] = this.BfOffSetBits[i - 10];
            if (i >= 14 && i <= 17) 
                vetor[i] = this.BiSize[i - 14];
            if (i >= 18 && i <= 21) 
                vetor[i] = this.BiWidth[i - 18];
            if (i >= 22 && i <= 25) 
                vetor[i] = this.BiHeight[i - 22];
            if (i == 26 || i == 27)
                vetor[i] = this.BiPlanes[i - 26];
            if (i == 28 || i == 29) 
                vetor[i] = this.BiBitCount[i - 28];
            if (i >= 30 && i <= 33) 
                vetor[i] = this.BiCompress[i - 30];
            if (i >= 34 && i <= 37)
                vetor[i] = this.BiSizeImag[i - 34];
            if (i >= 38 && i <= 41) 
                vetor[i] = this.BiXPPMeter[i - 38];
            if (i >= 42 && i <= 45)
                vetor[i] = this.BiYPPMeter[i - 42];
            if (i >= 46 && i <= 49) 
                vetor[i] = this.BiClrUsed[i - 46];
            if (i >= 50 && i <= 53) 
                vetor[i] = this.BiClrImpor[i - 50];
        }
        
        for(int i = 54; i < this.imagem.length; i++){
            vetor[i] = this.imagem[i - 54];
        }
        
        return vetor;
    }
    
    public FormatoBmp constuirBmpByteArray(byte[] vetor){
        FormatoBmp novoFormato = new FormatoBmp();
        
        //gerando a estrutura do bmp
        for (int i = 0; i < 54; i++) {            
            if (i == 0 || i == 1) 
                novoFormato.BfType[i] = vetor[i];
            if (i >= 2 && i <= 5) 
                novoFormato.BfSize[i - 2] = vetor[i];
            if (i == 6 || i == 7) 
                novoFormato.BfReser1[i - 6] = vetor[i];
            if (i == 8 || i == 9) 
                novoFormato.BfReser2[i - 8] = vetor[i];
            if (i >= 10 && i <= 13) 
                novoFormato.BfOffSetBits[i - 10] = vetor[i];
            if (i >= 14 && i <= 17) 
                novoFormato.BiSize[i - 14] = vetor[i];
            if (i >= 18 && i <= 21) 
                novoFormato.BiWidth[i - 18] = vetor[i];
            if (i >= 22 && i <= 25) 
                novoFormato.BiHeight[i - 22] = vetor[i];
            if (i == 26 || i == 27)
                novoFormato.BiPlanes[i - 26] = vetor[i];
            if (i == 28 || i == 29) 
                novoFormato.BiBitCount[i - 28] = vetor[i];
            if (i >= 30 && i <= 33) 
                novoFormato.BiCompress[i - 30] = vetor[i];
            if (i >= 34 && i <= 37)
                novoFormato.BiSizeImag[i - 34] = vetor[i];
            if (i >= 38 && i <= 41) 
                novoFormato.BiXPPMeter[i - 38] = vetor[i];
            if (i >= 42 && i <= 45)
                novoFormato.BiYPPMeter[i - 42] = vetor[i];
            if (i >= 46 && i <= 49) 
                novoFormato.BiClrUsed[i - 46] = vetor[i];
            if (i >= 50 && i <= 53) 
                novoFormato.BiClrImpor[i - 50] = vetor[i];
        }
        
        //gerando vetor de dados da imagem isso independe ta paleta de cores
        int inicioAreaDados = Conversoes.byteArray2Int4(novoFormato.BfOffSetBits);  //pega o inicio da area da imagem
        int tamanhoArquivo = Conversoes.byteArray2Int4(novoFormato.BfSize);         //pega o tamanho do arquivo em bytes
        int tamanhoImagem = tamanhoArquivo - inicioAreaDados;
        novoFormato.imagem = new byte[tamanhoImagem];

        for(int i = inicioAreaDados; i < tamanhoArquivo; i++){
            novoFormato.imagem[i - inicioAreaDados] = vetor[i];
        }
        
        return novoFormato;
    
    }

}
